home *** CD-ROM | disk | FTP | other *** search
/ Adobe Graphics & Publishing SDK 1996 December / Adobe Graphics & Publishing SDK 1996 December.iso / mac / Premiere 4.2 SDK r3 Mac / Examples / Projects / Device / Device.c < prev    next >
C/C++ Source or Header  |  1996-01-25  |  10KB  |  236 lines

  1. //========================================================================================
  2. //
  3. // Device.c - A skeleton device control module.
  4. //
  5. // Written by Randy Ubillos and Bryan K. "Beaker" Ressler.
  6. //
  7. // Copyright ⌐ 1993-96, Adobe Systems Incorporated, all rights reserved worldwide.
  8. //
  9. // Version    1.00    10/20/93    Original version.
  10. // Version    1.01    9/12/94        Updated for 4.0.
  11. // Version  1.02    11/8/95     Updated for 4.2 and CW7 - Added dsQuiet, cmdJog, and 
  12. //                                cmdEject, fDrvrQuiet, fHasJogMode, fHasEject.
  13. //
  14. //========================================================================================
  15.  
  16. //========================================================================================
  17. // Includes - use precompiled headers if compiling with CodeWarrior.
  18. //========================================================================================
  19. #ifdef __MWERKS__
  20.     #ifdef powerc
  21.         #include "PremierePPC"
  22.     #else
  23.         #include "Premiere68k"
  24.     #endif
  25. #else
  26.     #include "Premiere.h"
  27. #endif
  28.  
  29. //========================================================================================
  30. // Types
  31. //========================================================================================
  32. typedef struct {
  33.     short    mode;            // The "last reported mode" our device was in.
  34. } LocalRec, **LocalHand;
  35.  
  36. //========================================================================================
  37. // Static prototypes
  38. //========================================================================================
  39. static void DisplayAlert(short errNum, DeviceHand theData, LocalHand ldata);
  40. static short CheckConnection(LocalHand ldata);
  41.  
  42. //========================================================================================
  43. // Process commands to the device
  44. //========================================================================================
  45. pascal short main (short selector, DeviceHand theData)
  46. {
  47.     short        result = 0;
  48.     LocalHand    ldata;
  49.     
  50.     switch (selector) {
  51.         case dsInit:
  52.             // Create any local data here and return an error if could not complete. You
  53.             // might put a dialog for parameters here as well. This message is sent when
  54.             // user chooses a new device.
  55.             
  56.             // Allocate our locals handle and stuff it into theData. This will persist
  57.             // across calls.
  58.             (*theData)->deviceData = NewHandleClear(sizeof(LocalRec));
  59.             if ((*theData)->deviceData == nil)
  60.                 result = MemError();
  61.             ldata = (LocalHand)(*theData)->deviceData;
  62.             
  63.             // Set up any default values in the local data handle
  64.             if (result == noErr && ldata) {
  65.                 (*ldata)->mode = modeStop;
  66.             }
  67.             
  68.             // Attempt the default connection to the device.
  69.             if (result == noErr)
  70.                 result = CheckConnection(ldata);
  71.  
  72.             // Now that we've got a connection to our device, send ourselves a setup
  73.             // message.
  74.             if (result == noErr)
  75.                 result = main(dsSetup, theData);
  76.             break;
  77.             
  78.         case dsRestart:
  79.             // This message is the same as dsInit, exept the data handle has already been
  80.             // filled in (from data saved in a project file or the preferences file). You
  81.             // should verify the device connection, and open any needed drivers. This mes-
  82.             // sage is sent when restarting Premiere.
  83.             ldata = (LocalHand)(*theData)->deviceData;
  84.             result = CheckConnection(ldata);
  85.             if (result != noErr)
  86.                 DisplayAlert(1, theData, ldata);
  87.             break;
  88.             
  89.         case dsSetup:
  90.             // This message is sent when the user clicks the "Options╔" button in the
  91.             // Device Control preferences dialog. Return a non-zero value if the new set-
  92.             // tings fail (for instance, if they specify a different device and CheckCon-
  93.             // ection fails for that new device, return a non-zero value).
  94.             break;
  95.                                 
  96.         case dsQuiet:
  97.             // Disconnect from the device, but don't dispose of allocated structures yet.
  98.             // You'll get a dsCleanup for that.
  99.             break;
  100.             
  101.         case dsCleanup:
  102.             // Here is where we dispose of anything we allocated and close drivers that we
  103.             // opened. This message is sent at quit time.
  104.             DisposHandle((*theData)->deviceData);
  105.             break;
  106.             
  107.         case dsExecute:
  108.             // This message is where we perform actual device control and device inquiry
  109.             // tasks. Cache up ldata and then act based on the command.
  110.             ldata = (LocalHand)(*theData)->deviceData;
  111.             switch ((*theData)->command) {
  112.                 case cmdGetFeatures:
  113.                     // Here's where we tell Premiere about the features this device has.
  114.                     // We can OR as many of these together as apply.
  115.                     (*theData)->features = fBasic + fRecord + fCanShuttle + fCanJog +
  116.                                            fDrvrQuiet + fHasJogMode + fCanEject;
  117.                     break;
  118.                     
  119.                 case cmdStatus:
  120.                     // Premiere wants to know the current status of the device we're con-
  121.                     // nected to. Often it is not possible to instantly know the status of
  122.                     // a device. Premiere does cmdStatus calls all the time, and it
  123.                     // behooves the DevC not to waste any time here. The way some of the
  124.                     // built-in Premiere modules handle this is by keeping a "last record-
  125.                     // ed mode/location" value in their local data, and they use asynch-
  126.                     // ronous calls to their drivers. Each time into cmdStatus, if the
  127.                     // last async status call you made to your driver is ready, you copy
  128.                     // the mode and location into your "last recorded" values. If there's
  129.                     // not a status call queued up, go ahead and queue one up to your
  130.                     // driver. Finally, at the end of each cmdStatus call, just return
  131.                     // your last-recorded mode and location.
  132.                     (*theData)->timeformat = 0;            // 0: non-drop, 1: drop-frame
  133.                     (*theData)->timerate = 30;            // 24, 25 and 30 are valid
  134.                     (*theData)->timecode = 0;            // Current device location
  135.                     (*theData)->mode = modeStop;        // Current mode
  136.                     break;
  137.                 
  138.                 case cmdNewMode:
  139.                     // Here Premiere wants you to change the device into a new mode. If we
  140.                     // can't do it, the next cmdStatus call will reflect the old mode.
  141.                     // Normally you send the commands to the device here, even if they are
  142.                     // asynchronous.
  143.                     (*ldata)->mode = (*theData)->mode;
  144.                     break;
  145.                     
  146.                 case cmdGoto:
  147.                     // Premiere is telling you to move the device to the timecode spec-
  148.                     // ified in theData. Usually you start the device searching and return
  149.                     // without waiting for it to finish. Then Premiere will hammer
  150.                     // cmdStatus until the time matches the requested time. When the deck
  151.                     // is searching, your cmdStatus should return the mode as "modeGoto",
  152.                     // which will result in the text "Searching..." showing up in the
  153.                     // timecode display. This is the sorta lame, let-Premiere-do-the-work
  154.                     // way of doing timecode location -- if you can do cmdLocate, do it.
  155.  
  156.                     // Do whatever's necessary to move the device to (*theData)->timecode.
  157.                     break;
  158.                     
  159.                 case cmdLocate:
  160.                     // This is the synchronous way of doing timecode location. Premiere
  161.                     // wants you to move the deck to the specified timecode and return
  162.                     // with the deck in play mode rolling over timecode. You should use
  163.                     // the most accurate positioning you can here. Remember that you can
  164.                     // send yourself cmdStatus messages to find out what time your over.
  165.                     // Often you'll use some "rough seek" command to get your self within
  166.                     // a second or two before the requested code, then send yourself a
  167.                     // cmdNewMode to go into play mode. Then you sit in a tight loop
  168.                     // sending yourself cmdStatus messages until the time is equal to the
  169.                     // requested timecode, then you return as fast as possible. Don't try
  170.                     // to compensate for the latency between when you return and when
  171.                     // video actually gets captured. This is not really within your con-
  172.                     // trol, and Premiere has a calibration feature to take care of that
  173.                     // for you (by providing a preroll value).
  174.                     break;
  175.  
  176.                 case cmdShuttle:
  177.                     // Here Premiere is telling you to shuttle the deck either forward
  178.                     // or backward at a certain speed (the value is in (*theData)->mode).
  179.                     // -100 means 2x backwards playback, -50 means 1x backwards playback,
  180.                     // 0 means pause, 50 means 1x forward playback, and 100 means 2x
  181.                     // forwards playback. You may have to tweak this mapping to get the
  182.                     // right feel.
  183.                     break;
  184.  
  185.                 case cmdJogTo:
  186.                     // Here Premiere is telling you to quickly locate the deck at
  187.                     // (*theData)->timecode. That time will never be far from where you
  188.                     // currently are. The value for timecode is calculated by the distance
  189.                     // the user dragged the tractor tread on the screen.
  190.                     break;
  191.                     
  192.                 case cmdJog:
  193.                     // Here Premiere is telling you to jog at a rate specified in 'mode',
  194.                     // from -25 to +25.
  195.                     break;
  196.                     
  197.                 case cmdEject:
  198.                     // Here Premiere tells you to eject the media.
  199.                     break;
  200.             }
  201.             break;
  202.     }
  203.     return(result);
  204. }
  205.  
  206. //========================================================================================
  207. // Put up an error message
  208. //========================================================================================
  209. static void DisplayAlert(short errNum, DeviceHand theData, LocalHand ldata)
  210. {
  211. #ifdef applec
  212. #pragma unused(errNum, theData, ldata)
  213. #endif
  214.  
  215.     (*(**theData).PauseProc)();                // Pause the main program
  216.     
  217.     // Put up the proper alert box here
  218.     
  219.     (*(**theData).ResumeProc)();            // Restart the main program
  220. }
  221.  
  222. //========================================================================================
  223. // Check the device connection
  224. //========================================================================================
  225. static short CheckConnection(LocalHand ldata)
  226. {
  227. #ifdef applec
  228. #pragma unused(ldata)
  229. #endif
  230.  
  231.     // Check the device specified in 'ldata' and return 0 if connection is OK, non-zero
  232.     // otherwise.
  233.     
  234.     return(0);                                
  235. }
  236.